#include "tetgenParser.h"
#include "objParser.h"
#include "newmat.h"
#include "meshTools.h"


using namespace std;
using namespace MeshUtils;
using namespace NEWMAT;


int main(int argc, char* argv[])
{
    /*
	if(argc != 3)
	{
		cout << "usage : " << argv[0] << " mesh.tet" << endl;
		exit(0);
	}
*/
    int sflag = 0;
    int tflag = 0;
    char *cvalue = NULL;
    int index; 
    int c;

    while ((c = getopt (argc, argv, "st")) != -1)
        switch (c)
        {
            case 's':
                sflag = 1;
                break;
            case 't':
                tflag = 1;
                break;
            default:
                abort ();
        }



	if(!tflag)
	{
        TetgenParser parser(argv[1+tflag+sflag]);
		Mesh testMesh = parser.load();

		if(sflag)
            testMesh.subdivide();


		vector<Vector3> nodes;
		vector<Face_t> faces;
		map<unsigned int, unsigned int>& nodesMapBToV = testMesh.nodesMapBToV;
		testMesh.getBoundary(nodes, faces);

		vector<Vector3> normals;
		vector<Vector3> textures;

		unsigned int nbNodes = nodes.size();
		unsigned int nbFaces = faces.size();
		//ObjParser oParser(argv[1]);

		//oParser.load(nodes, normals, textures, faces, nbNodes, nbNorm, nbFaces);

		vector<Vector3> nodesTarget;
		vector<Vector3> normalsTarget;
		vector<Vector3> texturesTarget;
		vector<Face_t> facesTarget;
		unsigned int nbNodesTarget;
		unsigned int nbFacesTarget;
		unsigned int nbNormTarget;
		ObjParser oParserTarget(argv[2+tflag+sflag]);

		oParserTarget.load(nodesTarget, normalsTarget, texturesTarget, facesTarget, nbNodesTarget, nbNormTarget, nbFacesTarget);


		Matrix Vopt(1,1);

		optimizeTriangleMesh(nodes, testMesh.nodesMapBToV, faces, nodesTarget, facesTarget, Vopt);

		ofstream out("newMesh.obj");
		out << nbNodes << " 3 0 0" <<endl;
		for(unsigned int n = 0 ; n < nbNodes ; n++)
			out << "v " << Vopt(n*3+0+1,1) << " " << Vopt(n*3+1+1,1) << " " << Vopt(n*3+2+1,1) << endl;
			//out << n << " " << Vopt(n*3+0,0) << " " << Vopt(n*3+1,0) << " " << Vopt(n*3+2,0) << endl;
			//out << "v " << nodes[n].x << " " << nodes[n].y << " " << nodes[n].z << endl;
		for(unsigned int f = 0 ; f < nbFaces ; f++)
			out << "f " << faces[f].A+1 << " " << faces[f].B+1 << " " << faces[f].C+1 << endl;

		ofstream out2("newMesh.tet");
		out2 << nbNodes << " 3 0 0" <<endl;
		for(unsigned int n = 0 ; n < nbNodes ; n++)
			out2 << n << " " << Vopt(n*3+0+1,1) << " " << Vopt(n*3+1+1,1) << " " << Vopt(n*3+2+1,1) << endl;

		out2 << testMesh.elts.size() << " 4 0" <<endl;
		for(unsigned int t = 0 ; t < testMesh.elts.size() ; t++)
			out2 << t << " " <<  testMesh.elts[t].nodesList[0] << " " << testMesh.elts[t].nodesList[1] << " " << testMesh.elts[t].nodesList[2] << " " << testMesh.elts[t].nodesList[3] << endl;

		out2.close();


	}
	else
    {
		TetgenParser parser(argv[1+tflag+sflag]);
		Mesh testMesh = parser.load();

		if(sflag)
            testMesh.subdivide();


		vector<Vector3>& nodes = testMesh.nodes;


		unsigned int nbNodes = nodes.size();

		vector<Vector3> nodesTarget;
		vector<Vector3> normalsTarget;
		vector<Vector3> texturesTarget;
		vector<Face_t> facesTarget;
		unsigned int nbNodesTarget;
		unsigned int nbFacesTarget;
		unsigned int nbNormTarget;
		ObjParser oParserTarget(argv[2+tflag+sflag]);


		oParserTarget.load(nodesTarget, normalsTarget, texturesTarget, facesTarget, nbNodesTarget, nbNormTarget, nbFacesTarget);


		Matrix Vopt(1,1);
		unsigned int nbFaces; vector<Face_t> faces;
		optimizeTetraMesh(testMesh, nodes, testMesh.elts, nodesTarget, facesTarget, Vopt, nbFaces, faces);

		ofstream out("newMesh.obj");
		out << nbNodes << " 3 0 0" <<endl;
		for(unsigned int n = 0 ; n < nbNodes ; n++)
			out << "v " << Vopt(n*3+0+1,1) << " " << Vopt(n*3+1+1,1) << " " << Vopt(n*3+2+1,1) << endl;


		for(unsigned int f = 0 ; f < nbFaces ; f++)
			out << "f " << faces[f].A+1 << " " << faces[f].B+1 << " " << faces[f].C+1 << endl;

		out.close();
		ofstream out2("newMesh.tet");
		out2 << nbNodes << " 3 0 0" <<endl;
		for(unsigned int n = 0 ; n < nbNodes ; n++)
			out2 << n << " " << Vopt(n*3+0+1,1) << " " << Vopt(n*3+1+1,1) << " " << Vopt(n*3+2+1,1) << endl;

		out2 << testMesh.elts.size() << " 4 0" <<endl;
		for(unsigned int t = 0 ; t < testMesh.elts.size() ; t++)
			out2 << t << " " <<  testMesh.elts[t].nodesList[0] << " " << testMesh.elts[t].nodesList[1] << " " << testMesh.elts[t].nodesList[2] << " " << testMesh.elts[t].nodesList[3] << endl;

		out2.close();
	}


	return 0;
}
